﻿/* ***********************************************
 * Author		:  kingthy
 * Email		:  kingthy@gmail.com
 * Description	:  APIRequestBase
 *
 * ***********************************************/

using System;
using System.Collections.Generic;
using System.Text;
using OpenTwitter.SDK.Http;
using System.Xml;
using System.IO;

namespace OpenTwitter.SDK
{
    /// <summary>
    /// API接口请求的基类
    /// </summary>
    public abstract class APIRequestBase : WebRequest
    {
        /// <summary>
        /// 根据授权对象实例化对象
        /// </summary>
        /// <param name="oauth">OAuth授权对象</param>
        protected APIRequestBase(OAuthBase oauth)
        {
            this.OAuth = oauth;
            this.Charset = oauth.Charset;
            this.ResponseDataFormat = ResponseDataFormat.XML;
        }
        /// <summary>
        /// 授权对象
        /// </summary>
        public OAuthBase OAuth { get; private set; }
        /// <summary>
        /// 设置或返回获取数据的格式
        /// </summary>
        protected ResponseDataFormat ResponseDataFormat { get; set; }

        /// <summary>
        /// 请求并获取输出的数据, 如果有附加的文件上传则采用POST方式,否则默认采用GET方式
        /// </summary>
        /// <param name="requestUrl">API请求地址</param>
        /// <returns></returns>
        protected T GetResponseData<T>(string requestUrl)
            where T : ResponseObject
        {
            RequestMethod requestMethod = this.Files.Items.Count > 0 ? RequestMethod.POST : RequestMethod.GET;
            return this.GetResponseData<T>(requestMethod, requestUrl);
        }
        /// <summary>
        /// 请求并获取输出的数据
        /// </summary>
        /// <param name="requestMethod">请求方法.如GET或POST</param>
        /// <param name="requestUrl">API请求地址</param>
        /// <returns></returns>
        protected virtual T GetResponseData<T>(RequestMethod requestMethod, string requestUrl)
            where T : ResponseObject
        {
            this.ClearError();

            this.AddOAuthParameter(requestMethod, requestUrl);

            bool isPost = requestMethod == RequestMethod.POST;
            SyncHttpRequest request = new SyncHttpRequest(requestUrl, this.Charset);
            request.Headers.AddRange(this.Headers.Items);
            request.Parameters.AddRange(this.Parameters.Items);

            string data = string.Empty;
            try
            {
                if (isPost)
                {
                    if (this.Files.Items.Count > 0)
                    {
                        data = request.PostFile(this.Files);
                    }
                    else
                    {
                        data = request.Post();
                    }
                }
                else
                {
                    data = request.Get();
                }
            }
            catch (Exception ex)
            {
                this.OnError(ex);
                data = string.Empty;
            }

            if (string.IsNullOrEmpty(data)) return default(T);
            XmlDocument xml = new XmlDocument();
            try
            {
                xml.LoadXml(data);
            }
            catch (Exception ex)
            {
                this.OnError(ex);
                return null;
            }
            return ResponseObject.CreateInstance<T>(xml.DocumentElement);
        }

        /// <summary>
        /// 增加OAuth授权的参数
        /// </summary>
        /// <param name="requestMethod">请求方法.如GET或POST</param>
        /// <param name="requestUrl">API请求地址</param>
        /// <returns></returns>
        protected virtual void AddOAuthParameter(RequestMethod requestMethod, string requestUrl)
        {
            this.Parameters.Add("oauth_consumer_key", this.OAuth.AppKey);
            this.Parameters.Add("oauth_token", this.OAuth.Token);
            this.Parameters.Add("oauth_signature_method", "HMAC-SHA1");
            this.Parameters.Add("oauth_timestamp", Util.GenerateTimestamp().ToString());
            this.Parameters.Add("oauth_nonce", Util.GenerateRndNonce());
            this.Parameters.Add("oauth_version", "1.0");
            this.Parameters.Add("oauth_signature", this.OAuth.GenerateSignature(requestMethod, requestUrl, this.Parameters));
        }
    }
}
